// $Id: services.cpp 2 2009-09-02 08:47:42Z joseph2002 $
/*
 * Copyright 2009 Joseph Wu
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
 *
 * For more information, see http://xpcomplus.sourceforge.net
 */

#include <typeinfo>
#include <boost/test/unit_test.hpp>
#include <xpcom/component.hpp>
#include <xpcom/library.hpp>
#include <xpcom/result_code.hpp>
#include <xpcom/string.hpp>
#include "nsIServiceManager.hpp"
#include "nsIDirectoryService.hpp"
#include "nsIDirectoryServiceProvider.hpp"
#include "nsIDirectoryServiceProvider2.hpp"
#include "nsIFile.hpp"
#include "nsIObserverService.hpp"
#include "nsIProperties.hpp"
#include "nsISimpleEnumerator.hpp"

namespace {

const xpcom::uuid observer_cid = { 0xd07f5195, 0xe3d1, 0x11d2, { 0x8a, 0xcd, 0x0, 0x10, 0x5a, 0x1b, 0x88, 0x60 } };
const xpcom::uuid bad_observer_cid = { 0xF07f5195, 0xe3d1, 0x11d2, { 0x8a, 0xcd, 0x0, 0x10, 0x5a, 0x1b, 0x88, 0x60 } };

}

BOOST_AUTO_TEST_CASE(test_services_is_instantiated)
{
    using namespace xpcom;

    library lib;

    BOOST_CHECK(services.is_instantiated<nsIDirectoryService>("@mozilla.org/file/directory_service;1"));
    BOOST_CHECK(services.is_instantiated<nsIProperties>("@mozilla.org/file/directory_service;1"));
    BOOST_CHECK(!services.is_instantiated<nsIDirectoryService>("xxx@mozilla.org/file/directory_service;1"));
    BOOST_CHECK(!services.is_instantiated<nsIProperties>("xxx"));
    BOOST_CHECK(services.is_instantiated<interface>("@mozilla.org/observer-service;1"));
    BOOST_CHECK(services.is_instantiated<nsIObserverService>(observer_cid));
    BOOST_CHECK(!services.is_instantiated<nsIObserverService>(bad_observer_cid));
    BOOST_CHECK(!services.is_instantiated<nsIObserverService>(0));
    BOOST_CHECK(!services.is_instantiated<nsIFile>("@mozilla.org/observer-service;1"));
}

BOOST_AUTO_TEST_CASE(test_services)
{
    using namespace xpcom;

    library lib;

    {
        ref_ptr<nsIDirectoryService> p1 = services["@mozilla.org/file/directory_service;1"];
        BOOST_CHECK(p1);

        ref_ptr<nsIDirectoryServiceProvider2> p2 = services("@mozilla.org/file/directory_service;1");
        BOOST_CHECK(p2);

        bool persist;
        ref_ptr<nsIFile> home = p2->GetFile("Home", persist);
        string s = home->GetNativePath();
    }

    ref_ptr<nsIObserverService> p3 = services[observer_cid];
    BOOST_CHECK(p3);

    try {
        ref_ptr<nsIObserverService> p = services["xxx@mozilla.org/observer-service;1"];
        BOOST_CHECK(false);
    } catch (const xpcom::exception& e) {
        BOOST_CHECK(e.code() == NS_ERROR_FACTORY_NOT_REGISTERED);
    }

    try {
        ref_ptr<nsIObserverService> p = services[0];
        BOOST_CHECK(false);
    } catch (const xpcom::exception& e) {
        BOOST_CHECK(e.code() == NS_ERROR_NULL_POINTER);
    }

    try {
        ref_ptr<nsIObserverService> p = services(bad_observer_cid);
        BOOST_CHECK(false);
    } catch (const xpcom::exception& e) {
        BOOST_CHECK(e.code() == NS_ERROR_FACTORY_NOT_REGISTERED);
    }

    try {
        ref_ptr<nsIFile> p = services["@mozilla.org/observer-service;1"];
        BOOST_CHECK(false);
    } catch (const xpcom::exception& e) {
        BOOST_CHECK(e.code() == NS_ERROR_NO_INTERFACE);
    } catch (const std::bad_cast&) {
        BOOST_CHECK(true);
    }

}

BOOST_AUTO_TEST_CASE(test_services2)
{
    using namespace xpcom;

    library lib;
    ref_ptr<nsIServiceManager> m = lib.service_manager();

    {
        ref_ptr<nsIDirectoryService> p1 = services("@mozilla.org/file/directory_service;1", m);
        BOOST_CHECK(p1);

        ref_ptr<nsIDirectoryServiceProvider2> p2 = services("@mozilla.org/file/directory_service;1", m);
        BOOST_CHECK(p2);

        bool persist;
        ref_ptr<nsIFile> home = p2->GetFile("Home", persist);
    }

    ref_ptr<nsIObserverService> p3 = services(observer_cid, m);
    BOOST_CHECK(p3);

    try {
        ref_ptr<nsIObserverService> p = services("xxx@mozilla.org/observer-service;1", m);
        BOOST_CHECK(false);
    } catch (const xpcom::exception& e) {
        BOOST_CHECK(e.code() == NS_ERROR_FACTORY_NOT_REGISTERED);
    }

    try {
        ref_ptr<nsIObserverService> p = services(0, m);
        BOOST_CHECK(false);
    } catch (const xpcom::exception& e) {
        BOOST_CHECK(e.code() == NS_ERROR_NULL_POINTER);
    }

    try {
        ref_ptr<nsIObserverService> p = services(bad_observer_cid, m);
        BOOST_CHECK(false);
    } catch (const xpcom::exception& e) {
        BOOST_CHECK(e.code() == NS_ERROR_FACTORY_NOT_REGISTERED);
    }

    try {
        ref_ptr<nsIFile> p = services("@mozilla.org/observer-service;1", m);
        BOOST_CHECK(false);
    } catch (const xpcom::exception& e) {
        BOOST_CHECK(e.code() == NS_ERROR_NO_INTERFACE);
    } catch (const std::bad_cast&) {
        BOOST_CHECK(true);
    }

}
